﻿#region 참조 네임스페이스

using Skying.Diagnostics.Logger;
using Skying.Net.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

#endregion

namespace MJpegWriterRouter
{
	public partial class MainForm : Form
	{
		#region 변수

		private Logger _logger = Logger.GetLogger();

		/// <summary>
		/// 클라이언트의 접속을 받아들이는 TCP 리스너를 나타낸다.
		/// </summary>
		private TcpListener _listener;

		private IList<BaseSocket> _httpClients;

		#endregion

		#region 생성자/소멸자

		public MainForm()
		{
			this.InitializeComponent();

			this._httpClients = new List<BaseSocket>();
		}

		#endregion

		#region 버튼 이벤트

		/// <summary>
		/// Start 버튼이 클릭된 경우 발생하는 이벤트를 구현한다.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void StartButton_Click(object sender, EventArgs e)
		{
			try
			{
				int portNumber = (int)this.PortNumericUpDown.Value;

				this._listener = new TcpListener(portNumber, TransferType.Both, false);

				this._listener.ListeningStarted = (eventArgs) =>
				{
					string logString = string.Format("Listening @ {0}:{1}", this._listener.Address, this._listener.Port);

					this.ListenerStripStatusLabel.Text = logString;

					this.StartButton.Enabled = false;
					this.StopButton.Enabled = true;

					this._logger.Debug(logString);
				};

				this._listener.ListeningStopped = (eventArgs) =>
				{
					this.ListenerStripStatusLabel.Text = "Stopped";

					this.StartButton.Enabled = true;
					this.StopButton.Enabled = false;
					
					this._logger.Debug("Stopped");
				};

				this._listener.AcceptCompleted = (eventArgs) =>
				{
					this.ConnectedClientCountStripStatusLabel.Text = string.Format("{0} connected", this._listener.ClientsCount);

					if (eventArgs.Result.ClientType == ClientType.HTTP)
					{
						this._httpClients.Add(eventArgs.Result);
					}

					this._logger.Debug(string.Format("Client {0} conncedted from {1}:{2}", eventArgs.Result.Id, eventArgs.Result.Address, eventArgs.Result.Port));
				};

				this._listener.ClientDisconnected = (eventArgs) =>
				{
					this.ConnectedClientCountStripStatusLabel.Text = string.Format("{0} connected", this._listener.ClientsCount);

					this._httpClients.Remove(this._httpClients.First(t => t.Id.Equals(eventArgs.Result.Id)));

					this._logger.Debug(string.Format("Client {0} disconnected from {1}:{2}", eventArgs.Result.Id, eventArgs.Result.Address, eventArgs.Result.Port));
				};

				this._listener.Received = (eventArgs) =>
				{
					if (eventArgs == null)
					{
						this._logger.Warn("eventArgs is null.");

						return;
					}

					TransferEventArgs result = eventArgs.Result;

					byte[] buffer = new byte[result.DataStream.Length];

					foreach (BaseSocket client in this._httpClients)
					{
						client.SendAsynchrous(buffer);
					}
				};

				this._listener.Error = (eventArgs) =>
				{
					this._logger.Error(eventArgs.Result.Message);
				};

				this._listener.Listen();
			}
			catch (Exception error)
			{
				this._logger.Error(error);
			}
		}

		/// <summary>
		/// Stop 버튼이 클릭된 경우 발생하는 이벤트를 구현한다.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void StopButton_Click(object sender, EventArgs e)
		{
			try
			{
				if (!this._listener.IsListening) return;

				this._listener.Close();
			}
			catch (Exception error)
			{
				this._logger.Error(error);
			}
		}

		#endregion
	}
}